﻿///////////////////////////////////////////////////////////////////////////////
//
// This file is part of the BassDrop project
//   https://code.google.com/p/bass-drop/
//
//
// Creator:	Gergely Krajcsovszki (krajcsovszkig@hotmail.com)
// Date:	2013-12-23 11:40
//
//
// Copyright © 2013-2014. Gergely Krajcsovszki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BassDrop.Core.Common.Services;

namespace BassDrop.Core.Common.Plugins
{
	/// <summary>
	/// Base class of the main objects of all plugins
	/// </summary>
	public abstract class PluginObjectBase : INotifyPropertyChanged
	{
		/// <summary>
		/// The descriptor object of the plugin owning this object
		/// </summary>
		public virtual BassDropPluginBase PluginDescriptor
		{
			get;
			private set;
		}

		/// <summary>
		/// The name of this plugin instance
		/// </summary>
		public virtual string InstanceName
		{
			get;
			private set;
		}

		private PluginOptionsSetBase m_options;

		/// <summary>
		/// The options of this plugin instance
		/// </summary>
		public virtual PluginOptionsSetBase Options
		{
			get
			{
				return m_options;
			}

			protected set
			{
				if ( value != m_options )
				{
					if ( m_options != null )
					{
						m_options.PropertyChanged -= m_options_PropertyChanged;
					}

					m_options = value;

					if ( m_options != null )
					{
						m_options.PropertyChanged -= m_options_PropertyChanged;
						m_options.PropertyChanged += m_options_PropertyChanged;
					}

					OnSettingsChanged( m_options, new PropertyChangedEventArgs( "Options" ) );
				}
			}
		}

		/// <summary>
		/// Event fired when the settings of the plugin or its instances change
		/// </summary>
		public event PropertyChangedEventHandler SettingsChanged;

		/// <summary>
		/// Fire a new SettingsChanged event
		/// </summary>
		/// <param name="settings"></param>
		/// <param name="e"></param>
		private void OnSettingsChanged( PluginOptionsSetBase settings, PropertyChangedEventArgs e )
		{
			if ( SettingsChanged != null )
			{
				SettingsChanged( settings, e );
			}
		}

		/// <summary>
		/// Constructs a new plugin main object
		/// </summary>
		/// <param name="pluginDescriptor">The descriptor object of the plugin owning this object</param>
		/// <param name="instanceName">the name of this plugin instance</param>
		protected PluginObjectBase( BassDropPluginBase pluginDescriptor, string instanceName )
		{
			PluginDescriptor = pluginDescriptor;
			InstanceName = instanceName;
		}

		/// <summary>
		/// Loads the options
		/// </summary>
		/// <param name="settings">the seettings object to load from</param>
		public async Task Load( ISettings settings )
		{
			if ( Options != null )
			{
				await Options.Load( settings );
			}
		}

		/// <summary>
		/// Saves the options
		/// </summary>
		/// <param name="settings">the seettings object to save to</param>
		public void Save( ISettings settings )
		{
			if ( Options != null )
			{
				Options.Save( settings );
			}
		}
		private void m_options_PropertyChanged( object sender, PropertyChangedEventArgs e )
		{
			OnSettingsChanged( (PluginOptionsSetBase) sender, e );
		}

		#region Events

		/// <summary>
		/// Event fired when one of the properties of this object changes
		/// </summary>
		public event PropertyChangedEventHandler PropertyChanged;

		/// <summary>
		/// Fires a new PropertyChanged event with the passed arguments
		/// </summary>
		/// <param name="propertyName"></param>
		protected virtual void OnPropertyChanged( string propertyName )
		{
			if ( PropertyChanged != null )
			{
				PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
			}
		}

		/// <summary>
		/// Event fired when one of the properties making up the state of this object changes
		/// </summary>
		public event PropertyChangedEventHandler StateChanged;

		/// <summary>
		/// Fires a new StateChanged event with the passed arguments
		/// </summary>
		/// <param name="propertyName"></param>
		protected virtual void OnStateChanged( string propertyName )
		{
			if ( StateChanged != null )
			{
				StateChanged( this, new PropertyChangedEventArgs( propertyName ) );
			}
		}

		#endregion Events
	}
}
